package ${groupId}.${artifactIdProjectPackageName}.exception.handle;

import ${groupId}.${artifactIdProjectPackageName}.exception.${mainClassPrefix}ErrorCode;
import ${groupId}.${artifactIdProjectPackageName}.exception.RedirectException;
import ${groupId}.${artifactIdProjectPackageName}.exception.ServiceException;
import ${groupId}.${artifactIdProjectPackageName}.common.result.ResultSet;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;


@ControllerAdvice
public class AllExceptionHandle {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResultSet allPointerException(Exception e) {
        e.printStackTrace();
        logger.error("统一异常处理",e);
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.EXCEPTION);
    }

//    @ResponseBody
//    @ExceptionHandler(RpcException.class)
//    public ResultSet rpcException(RpcException e) {
//        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.EXCEPTION,"内部服务调用异常");
//    }



    @ResponseBody
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultSet redirectException(HttpRequestMethodNotSupportedException e) {
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.EXCEPTION, e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(RedirectException.class)
    public ResultSet redirectException(HttpServletRequest req, HttpServletResponse res, RedirectException e) {
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.REDIRECT, e.getUrl());
    }

    @ResponseBody
    @ExceptionHandler(ServiceException.class)
    public ResultSet serviceException(HttpServletRequest req, HttpServletResponse res, ServiceException e) {
        return e.getResultSet();
    }

    @Data
    @AllArgsConstructor
    public class FieldErr{

        private String fieldName;

        private String errMsg;


    }

    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultSet MethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        StringBuffer sb = new StringBuffer();

        List<ObjectError> allErrors = exception.getBindingResult().getAllErrors();
        ArrayList<FieldErr> fieldErrors = new ArrayList<>();
        for (ObjectError allError : allErrors) {
            if(allError instanceof FieldError){
                FieldError fieldError = (FieldError)allError;
                fieldErrors.add(new FieldErr(fieldError.getField(),fieldError.getDefaultMessage()));

                sb.append("[" + fieldError.getField() + "]" + fieldError.getDefaultMessage() + ",");
            }
        }
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.PARAMETER_ERROR, sb.toString(),fieldErrors);
    }


    @ResponseBody
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResultSet MethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException exception) {
        String msg = String.format("类型转换错误，参数：%s，非法值：%s，错误信息：%s", exception.getName(), exception.getValue(), exception.getMessage());
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.PARAMETER_ERROR, msg);
    }

    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    public ResultSet ConstraintViolationException(ConstraintViolationException exception) {
        String msg = exception.getConstraintViolations().iterator().next().getMessage();
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.PARAMETER_ERROR, msg);
    }

    @ResponseBody
    @ExceptionHandler(BindException.class)
    public ResultSet bindException(BindException exception) {
        String msg = exception.getBindingResult().getFieldError().getDefaultMessage();
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.PARAMETER_ERROR, msg);
    }

    @ResponseBody
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultSet missingServletRequestParameterException(MissingServletRequestParameterException exception) {
        String msg = "缺少参数：" + exception.getParameterName();
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.PARAMETER_ERROR, msg);
    }


    @ResponseBody
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResultSet httpMessageNotReadableException(HttpMessageNotReadableException exception) {
        return ResultSet.builderFail(${mainClassPrefix}ErrorCode.PARAMETER_ERROR, "格式有误");
    }



}
